'use strict';

const Controller = require('egg').Controller;
const config = require("../../../config/wx");
const path = require("path");
const fs = require("fs");
const crypto = require("crypto");
const {OrderStatusEnum} = require("../../utils/enum");
const dayjs = require("dayjs");
const {formatDecimal} = require("../../utils");
function generateNonceStr(len) {
    let data = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
    let str = "";
    for (let i = 0; i < len; i++) {
        str += data.charAt(Math.floor(Math.random() * data.length));
    }
    return str;
}
class WxPayController extends Controller {
    /**
     * 创建支付订单
     */
    async createPayment() {
        const { order_id } = this.ctx.request.body;
        const order = await this.ctx.model.Business.Order.findOne({
            where: {
                id: order_id
            },
            include: [
                { model: this.ctx.model.Business.User, as: 'user' }
            ],
            raw: true
        })
        if (!order) {
            throw new Error("订单不存在");
        }
        if (!order.user_id) {
            throw new Error("用户不存在");
        }
        const { openid } = await this.ctx.model.Business.User.findOne({
            where: {
                id: order.user_id
            },
            raw: true
        })
        if (!openid) {
            throw new Error("用户openid不存在");
        }
        // 判断订单是否已经支付否
        if (order.prepay_id && order.time_expire > new Date()) {
            this.ctx.success(this.createPaySign(order.prepay_id));
            return
        }
        const { payment_amount } = order;
        const res = await this.createPayOrder({
            payment_amount: payment_amount,
            desc: '商品购买',
            order_no: order.order_no,
            openid,
            notify_url: config.notify_url,
        })

        this.ctx.success({
            ...res
        });
    }
    async createPayOrder({ payment_amount, desc, order_no, openid, notify_url }) {
        console.log({ payment_amount, desc, order_no, openid, notify_url })
        // 生成订单号（保证唯一性：我采用时间戳拼6位随机数的方式）
        const time_expire = new Date(Date.now() + 1000 * 60 * 15).toISOString()
        const createOrderParams = {
            appid: config.appid,
            mchid: config.mch_id,
            description: desc,
            out_trade_no: order_no,
            time_expire: time_expire,
            notify_url,
            amount: {
                // payment_amount
                "total" : Math.ceil(payment_amount * 100),
                "currency" : "CNY"
            },
            payer: {
                openid
            }
        }
        let timeStamp = Math.floor(new Date().getTime() / 1000)
        let nonceStr = generateNonceStr(32)
        const Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="${config.mch_id}",nonce_str="${nonceStr}",signature="${this.createOrderSign('POST',
            '/v3/pay/transactions/jsapi',
            timeStamp,
            nonceStr,
            createOrderParams
        )}",timestamp="${timeStamp}",serial_no="${config.serial_no}"`
        // 下单获取prepay_id
        const createPayRes = await this.ctx.curl(
            "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",
            {
                method: "post",
                data: createOrderParams,
                headers: {
                    Authorization: Authorization,
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
                dataType: 'json'
            }
        );
        console.log(createOrderParams, 'createOrderParams')
        if (createPayRes.data.prepay_id) {
            // 把参数+签名返回给前端
            const result = this.createPaySign(createPayRes.data.prepay_id)
            await this.ctx.model.Business.Order.update({
                prepay_id: createPayRes.data.prepay_id,
                time_expire: time_expire
            }, {
                where: {
                    order_no
                }
            })
            return {
                ...result,
                order_no
            }
        } else {
            throw new Error(createPayRes.data.message);
        }
    }
    /**
     * 微信支付v3 下单签名值生成
     * @param {string} method 请求方法
     * @param {string} url  微信小程序下单官方api
     * @param {number} timestamp 时间戳 秒级
     * @param {string} nonce_str 随机字符串
     * @param {Object} order 主体（订单）信息
     */
    createOrderSign(method, url, timestamp, nonce_str, order) {
        // 签名串
        let signStr = `${method}\n${url}\n${timestamp}\n${nonce_str}\n${JSON.stringify(
            order
        )}\n`;
        // 读取API证书文件内容 apiclient_key.pem的内容
        const filepath = path.join('app', '/public/apiclient_key.pem');
        let cert = fs.readFileSync(filepath, "utf-8");
        // 创建使用 RSA 算法和 SHA-256 散列算法的签名对象
        let sign = crypto.createSign("RSA-SHA256");
        // 对签名串进行加密处理
        sign.update(signStr);
        return sign.sign(cert, "base64");
    }

    createPaySign(prepay_id) {
        let timeStamp = Math.floor(new Date().getTime() / 1000)
        let nonceStr = generateNonceStr(32);
        let signStr = `${config.appid}\n${timeStamp}\n${nonceStr}\nprepay_id=${prepay_id}\n`;
        const filepath = path.join('app', '/public/apiclient_key.pem');
        let cert = fs.readFileSync(filepath, "utf-8");
        let sign = crypto.createSign("RSA-SHA256");
        sign.update(signStr);
        let paySign = sign.sign(cert, "base64");
        return {
            paySign: paySign,
            timestamp: timeStamp + '',
            nonce_str: nonceStr,
            signType: 'RSA',
            package: 'prepay_id=' + prepay_id
        };
    }
    // 微信支付回调地址
    async decodePayNotify(resource) {
        try {
            const AUTH_KEY_LENGTH = 16;
            // ciphertext = 密文，associated_data = 填充内容， nonce = 位移
            const { ciphertext, associated_data, nonce } = resource;
            // 密钥
            const key_bytes = Buffer.from(config.key, 'utf8');
            // 位移
            const nonce_bytes = Buffer.from(nonce, 'utf8');
            // 填充内容
            const associated_data_bytes = Buffer.from(associated_data, 'utf8');
            // 密文Buffer
            const ciphertext_bytes = Buffer.from(ciphertext, 'base64');
            // 计算减去16位长度
            const cipherdata_length = ciphertext_bytes.length - AUTH_KEY_LENGTH;
            // upodata
            const cipherdata_bytes = ciphertext_bytes.slice(0, cipherdata_length);
            // tag
            const auth_tag_bytes = ciphertext_bytes.slice(cipherdata_length, ciphertext_bytes.length);
            const decipher = crypto.createDecipheriv(
                'aes-256-gcm', key_bytes, nonce_bytes
            );
            decipher.setAuthTag(auth_tag_bytes);
            decipher.setAAD(Buffer.from(associated_data_bytes));
            const output = Buffer.concat([
                decipher.update(cipherdata_bytes),
                decipher.final(),
            ]);
            // 解密后 转成 JSON 格式输出
            return JSON.parse(output.toString('utf8'));
        }
        catch (error){
            console.error('解密错误:', error);
            return null;
        }

    }

    /**
     * 微信支付回调
     * @param {Object} req - 请求对象，包含查询参数
     * url  https://qy.xxx.com/v1/payment/wx/success
     */
    async paymentWxNotify() {
        try {
            const { ctx } = this;
            const result = ctx.request.body;
            // 记录日志
            this.ctx.logger.info('订单回调', {
                result: result
            });
            if (result.event_type === 'TRANSACTION.SUCCESS') {
                // 解密微信支付成功后的订单信息
                const deInfo = await this.decodePayNotify(result.resource)
                // 快递单-待发货
                const order = await this.ctx.model.Business.Order.findOne({
                    where: {
                        order_no: deInfo.out_trade_no,
                    },
                    raw: true
                })
                this.ctx.logger.info('订单回调成功', {
                    order,
                    deInfo
                });
                if (!order) {
                    return false
                }
                await this.ctx.model.Business.Order.update({
                    status: OrderStatusEnum.PENDING_VERIFICATION,
                    transaction_id: deInfo.transaction_id,
                    payment_time: deInfo.success_time,
                },{
                    where: {
                        order_no: deInfo.out_trade_no
                    }
                })
                // 支付成功
                this.ctx.success('success', 200);
            } else {
                // 支付失败
                this.ctx.error(500,'支付回调错误', 500);
            }
        }
        catch (err) {
            this.ctx.logger.info('订单回调失败', {
                err
            });
            this.ctx.error(500,'支付回调错误', 500);
        }
    }
    // 退款回调
    async refundWxNotify() {
        try {
            const { ctx } = this;
            const result = ctx.request.body;
            // 解密微信支付成功后的订单信息
            const deInfo = await this.decodePayNotify(result.resource)
            if (result.event_type === 'REFUND.SUCCESS') {
                await this.ctx.model.Business.Order.update({
                    status: OrderStatusEnum.REFUNDED,
                    refund_success_time: new Date()
                },{
                    where: {
                        order_no: deInfo.out_trade_no
                    }
                })
                // 支付成功
                this.ctx.success('success', 200);
            } else if (result.event_type === 'REFUND.ABNORMAL'){
                await this.ctx.model.Business.Order.update({
                    status: OrderStatusEnum.REFUNDING,
                    refund_remark: '退款失败',
                    refund_success_time: new Date()
                },{
                    where: {
                        order_no: deInfo.out_trade_no
                    }
                })
                // 支付失败
                this.ctx.error(500,'支付回调错误', 500);
            } else {
                // 支付失败
                this.ctx.error(500,'支付回调错误', 500);
            }
        }
        catch (err) {
            this.ctx.error(500,'支付回调错误', 500);
        }
    }


    /**
     * 充值回调
     */
    async rechargeWxNotify() {
        const transaction = await this.ctx.model.transaction();
        try {
            const { ctx } = this;
            const result = ctx.request.body;
            // let result = {
            //     id: '4206b00a-61c0-56a6-8756-d76a757959e6',
            //     create_time: '2025-07-18T01:10:02+08:00',
            //     resource_type: 'encrypt-resource',
            //     event_type: 'TRANSACTION.SUCCESS',
            //     summary: '支付成功',
            //     resource: {
            //         original_type: 'transaction',
            //         algorithm: 'AEAD_AES_256_GCM',
            //         ciphertext: 'QyhgRADRGzbrp4vEkwPPvtmnKBNNRwHod9LXAyUQ4FDCNucvAy0dlP+tjRcLJe7/4rQX/gSeZwh+IKsOurlvX3rAGE9l7qes4LstJede8qXQFaXiLNRar3SjN+V7dkIIQsG9So/WrVue/bk4g9z859uFbi2jPjiHI9Tk861TtIO4JKWgCIBpeD4GUn78hWiqeb99vqPMK5B3zTqyMAY2QhHYSIhr4eqLamROOzQUX9ExYpDRCk25P5QFc1ABwmRULuGGuPtXiKSfI01g2mW6+HPewUKnw9XIJme615SlEzje+vROIzfpltTcEEEIoHD0ArGLenIFmSx+TqZ2oWaMuRiU/Zlc0h5rDojAahSs5DEygmcBXS6cfja4LKfJgohe+/NU4vw54cKldp2W2O7bUIN58DwMedc7WoixNoiGVgRBW8EKxaK2lL6bsFA4r7wJMrGgjA+s8hKZhQhSxQV7VlBv4i3ZLAASdydby2rrz9K7ItCFAA2BahOQ9bxGHazg1nIym0tyNHJC42MISAoL2GDnGeW7J5ZyIbREN179eR5eDKxLwLWKaRtqsav3DIqmRUme',
            //         associated_data: 'transaction',
            //         nonce: 'ZbFwbIhOgijY'
            //     }
            // }
            // 记录日志
            this.ctx.logger.info('订单回调失败', {
                result
            });
            if (result.event_type === 'TRANSACTION.SUCCESS') {
                // 解密微信支付成功后的订单信息
                const deInfo = await this.decodePayNotify(result.resource)
                // 快递单-待发货
                const order = await this.ctx.model.Business.Order.findOne({
                    where: {
                        order_no: deInfo.out_trade_no,
                    },
                    raw: true
                })
                this.ctx.logger.info('订单回调成功', {
                    order,
                    deInfo
                });
                if (!order) {
                    return false
                }
                const userCard = await ctx.model.Business.UserCard.findOne({
                    where: {
                        user_id: order.user_id,
                    }
                })
                let userCardId = 0
                if (userCard) {
                    userCardId = userCard.id
                    // 升级更新
                    await ctx.model.Business.UserCard.update({
                        user_level_id: order.user_level_id,
                        // 充值总金额增加 total_recharge
                        total_recharge: this.ctx.model.Sequelize.literal(`total_recharge + ${order.payment_amount}`),
                        current_balance: this.ctx.model.Sequelize.literal(`current_balance + ${order.payment_amount}`),
                    }, {
                        transaction,
                        where: {
                            id: userCardId
                        }
                    })
                } else {
                    console.log('order',order)
                    // 开通新卡
                   const newUserCard = await ctx.model.Business.UserCard.create({
                        card_no: this.ctx.service.business.userCard.generateCardNo(),
                        user_id: order.user_id,
                       level_id: order.user_level_id,
                       expire_time: dayjs().add(99, 'year').toDate(),
                        total_recharge: order.payment_amount,
                        current_balance: order.payment_amount,
                       gift_product_used: 5,
                       gift_product_remaining: 10
                    },{
                        transaction,
                    })
                    userCardId = newUserCard.id
                }

                await this.ctx.model.Business.Order.update({
                    status: OrderStatusEnum.COMPLETED,
                    transaction_id: deInfo.transaction_id,
                    payment_time: deInfo.success_time,
                    user_card_id: userCardId
                },{
                    where: {
                        order_no: deInfo.out_trade_no
                    },
                    transaction
                })
                // 创建余额变动记录
                await ctx.model.Business.BalanceRecord.create({
                    user_id: order.user_id,
                    amount: formatDecimal(order.payment_amount),
                    user_card_id: userCardId,
                    user_type: 1,
                    type: 5,
                    description: '会员充值'
                },{
                    transaction
                })
                await transaction.commit();
                // 支付成功
                this.ctx.success('success', 200);
            } else {
                // 支付失败
                this.ctx.error(500,'支付回调错误');
                this.ctx.logger.info('订单回调失败', {
                    result
                });
            }
        }
        catch (err) {
            await transaction.rollback();
            console.log(err)
            this.ctx.logger.info('订单回调失败', {
                err
            });
            this.ctx.error(500,'支付回调错误', 500);
        }
    }

}

module.exports = WxPayController;
